home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 351-375 / disk_352 / printhandler / print-handler.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  13KB  |  673 lines

  1. /* $Revision Header *** Header built automatically - do not edit! ***********
  2.  *
  3.  *    (C) Copyright 1990 by MXM
  4.  *
  5.  *    Name .....: Print-Handler.c
  6.  *    Created ..: Wednesday 11-Apr-90 09:51
  7.  *    Revision .: 6
  8.  *
  9.  *    Date            Author          Comment
  10.  *    =========       ========        ====================
  11.  *    11-Apr-90       Olsen           Created this file!
  12.  *
  13.  ****************************************************************************
  14.  *
  15.  *    Notez-bien: This version of Print-Handler will only compile under
  16.  *                  Aztec 'C' 5.0. Some effort must be taken to adapt it
  17.  *                  for Lattice 'C' 5.0.
  18.  *
  19.  *    I've left all my debugs in and commented them out. This should
  20.  *    compile fine now.
  21.  *
  22.  * $Revision Header ********************************************************/
  23.  
  24.     /* Function prototypes (no includes this time). */
  25.  
  26. struct DataSeg *    CreateSeg(APTR,LONG);
  27. struct DataSeg *    DeleteSeg(struct DataSeg *);
  28. VOID            ReturnPacket(struct DosPacket *,ULONG,ULONG);
  29. struct DosPacket *    TaskWait(VOID);
  30. LONG            PrintIt(APTR,LONG);
  31. LONG            PrintData(UBYTE *,LONG,struct PopSupport *);
  32. VOID *            SendCustomMsg(LONG);
  33.  
  34. VOID            QueueEntryPoint(VOID);
  35. LONG            _main(VOID);
  36.  
  37.     /* This structure is used to hold a fragment of the file to
  38.      * be printed.
  39.      */
  40.  
  41. struct DataSeg
  42. {
  43.     struct DataSeg    *NextSeg;
  44.  
  45.     APTR         Buffer;
  46.     LONG         Length;
  47. };
  48.  
  49.     /* Shared library structures. */
  50.  
  51. struct IntuitionBase    *IntuitionBase;
  52. struct MXMBase        *MXMBase;
  53. /*struct Library        *FarBase;*/
  54. extern struct ExecBase    *SysBase;
  55.  
  56.     /* This is the maximum length of a printer line. */
  57.  
  58. #define MAXPRINT    1024
  59.  
  60.     /* This is the maximum number of available slots. */
  61.  
  62. #define MAXSLOT        128
  63.  
  64.     /* Handshake signal. */
  65.  
  66. #define SIG_SHAKE    SIGBREAKF_CTRL_D
  67.  
  68.     /* Some more global data. */
  69.  
  70. struct Preferences    *Preferences;
  71. struct IOStdReq        *PrinterDevice;
  72. struct Process        *QueueProc;
  73. struct Process        *HandlerProc;
  74. struct DataSeg        *DataSegs[MAXSLOT];
  75. UBYTE             Available[MAXSLOT];
  76. UBYTE             LineStack[MAXPRINT];
  77.  
  78.     /* Working stats for the printer process. */
  79.  
  80. LONG LinesDone = 0,ColumnsDone = 0;
  81.  
  82.     /* _main():
  83.      *
  84.      *    This is the main entry point to the handler
  85.      *    process.
  86.      */
  87.  
  88. LONG
  89. _main()
  90. {
  91.     struct DosPacket    *PrintPacket;
  92.     struct DeviceNode    *PrintNode;
  93.     LONG             OpenCount = 0,i;
  94.  
  95.         /* Mark all buffers as vacant. */
  96.  
  97.     memset(Available,TRUE,MAXSLOT);
  98.  
  99.     HandlerProc = (struct Process *)SysBase -> ThisTask;
  100.  
  101.         /* Started from CLI? */
  102.  
  103.     if(HandlerProc -> pr_CLI)
  104.         return(-1);
  105.  
  106.         /* Wait for parameter packet. */
  107.  
  108.     PrintPacket = TaskWait();
  109.  
  110.         /* Pointer to our own DeviceNode. */
  111.  
  112.     PrintNode = (struct DeviceNode *)BADDR(PrintPacket -> dp_Arg3);
  113.  
  114.         /* Open mxm.library. */
  115.  
  116.     if(!(MXMBase = (struct MXMBase *)OpenLibrary("mxm.library",34)))
  117.     {
  118.         ReturnPacket(PrintPacket,DOSFALSE,PrintPacket -> dp_Res2);
  119.         goto FallOff;
  120.     }
  121.  
  122. /*    if(!(FarBase = OpenLibrary("farprint.library",0)))*/
  123. /*    {*/
  124. /*        ReturnPacket(PrintPacket,DOSFALSE,PrintPacket -> dp_Res2);*/
  125. /*        goto FallOff;*/
  126. /*    }*/
  127.  
  128.         /* Extract global library vector. */
  129.  
  130.     IntuitionBase = (struct IntuitionBase *)MXMBase -> IntuitionBase;
  131.  
  132.         /* Create the printer process. */
  133.  
  134.     if(!(QueueProc = CreateFuncProc("Print-Handler.queue",10,QueueEntryPoint,4096)))
  135.     {
  136.         ReturnPacket(PrintPacket,DOSFALSE,PrintPacket -> dp_Res2);
  137.         goto FallOff;
  138.     }
  139.  
  140.         /* Wait for a reply. */
  141.  
  142.     Wait(SIG_SHAKE);
  143.  
  144.         /* Process quietly removed itself. */
  145.  
  146.     if(!QueueProc)
  147.     {
  148.         ReturnPacket(PrintPacket,DOSFALSE,PrintPacket -> dp_Res2);
  149.         goto FallOff;
  150.     }
  151.  
  152.         /* We're on the scene now. */
  153.  
  154.     PrintNode -> dn_Task = &HandlerProc -> pr_MsgPort;
  155.  
  156.         /* Return the compliment. */
  157.  
  158.     ReturnPacket(PrintPacket,DOSTRUE,PrintPacket -> dp_Res2);
  159.  
  160.         /* Go into loop. */
  161.  
  162.     for(;;)
  163.     {
  164.             /* Wait for the packet. */
  165.  
  166. /*        SendText("TaskWait");*/
  167.  
  168.         PrintPacket = TaskWait();
  169.  
  170. /*        SendText("Type = %ld",PrintPacket -> dp_Type);*/
  171.  
  172.         switch(PrintPacket -> dp_Type)
  173.         {
  174.                 /* Somebody Open()ed us. */
  175.  
  176.             case ACTION_FINDINPUT:
  177.             case ACTION_FINDOUTPUT:
  178.             case ACTION_FINDUPDATE:
  179.             {
  180.                 struct FileHandle *FileHandle = (struct FileHandle *)BADDR(PrintPacket -> dp_Arg1);
  181.  
  182. /*                SendText("Open");*/
  183.  
  184.                     /* Assume failure. */
  185.  
  186.                 FileHandle -> fh_Port = DOSFALSE;
  187.  
  188.                     /* Look for an empty buffer. */
  189.  
  190.                 for(i = 0 ; i < MAXSLOT ; i++)
  191.                 {
  192.                     if(Available[i])
  193.                     {
  194.                         FileHandle -> fh_Port = (struct MsgPort *)DOSTRUE;
  195.                         FileHandle -> fh_Arg1 = i;
  196.  
  197.                         Available[i] = FALSE;
  198.  
  199. /*                        SendText("Clean open! -> %ld.",i);*/
  200.  
  201.                         OpenCount++;
  202.  
  203.                         break;
  204.                     }
  205.                 }
  206.  
  207.                 ReturnPacket(PrintPacket,(LONG)FileHandle -> fh_Port,PrintPacket -> dp_Res2);
  208.                 break;
  209.             }
  210.  
  211.                 /* A FileHandle got closed. */
  212.  
  213.             case ACTION_END:
  214.             {
  215.                 OpenCount--;
  216.  
  217. /*                SendText("Close -> %ld",PrintPacket -> dp_Arg1);*/
  218.  
  219.                 SendCustomMsg(PrintPacket -> dp_Arg1);
  220.  
  221.                 ReturnPacket(PrintPacket,DOSTRUE,PrintPacket -> dp_Res2);
  222.  
  223.                 break;
  224.             }
  225.  
  226.                 /* We always read *nothing*. */
  227.  
  228.             case ACTION_READ:
  229.             {
  230. /*                SendText("Read -> %ld",PrintPacket -> dp_Arg1);*/
  231.  
  232.                 ReturnPacket(PrintPacket,NULL,PrintPacket -> dp_Res2);
  233.                 break;
  234.             }
  235.  
  236.                 /* Something gets written to a FileHandle. */
  237.  
  238.             case ACTION_WRITE:
  239.             {
  240.                 char *Buffer = (char *)PrintPacket -> dp_Arg2;
  241.                 struct DataSeg *NextSlot;
  242.  
  243. /*                SendText("Write -> %ld Bytes %ld Buffer %lx",PrintPacket -> dp_Arg1,PrintPacket -> dp_Arg3,Buffer);*/
  244.  
  245.                 PrintPacket -> dp_Res1 = PrintPacket -> dp_Arg3;
  246.  
  247.                     /* Add the new data. */
  248.  
  249.                 if(!DataSegs[PrintPacket -> dp_Arg1])
  250.                 {
  251.                     if(!(DataSegs[PrintPacket -> dp_Arg1] = CreateSeg((APTR)Buffer,PrintPacket -> dp_Arg3)))
  252.                     {
  253.                         PrintPacket -> dp_Res2 = ERROR_NO_FREE_STORE;
  254.                         PrintPacket -> dp_Res1 = 0;
  255.                     }
  256. /*                    else*/
  257. /*                        SendText("Created.");*/
  258.                 }
  259.                 else
  260.                 {
  261.                     NextSlot = DataSegs[PrintPacket -> dp_Arg1];
  262.  
  263.                     while(NextSlot -> NextSeg)
  264.                         NextSlot = NextSlot -> NextSeg;
  265.  
  266.                     if(!(NextSlot -> NextSeg = CreateSeg((APTR)Buffer,PrintPacket -> dp_Arg3)))
  267.                     {
  268.                         PrintPacket -> dp_Res2 = ERROR_NO_FREE_STORE;
  269.                         PrintPacket -> dp_Res1 = 0;
  270.                     }
  271. /*                    else*/
  272. /*                        SendText("Appended.");*/
  273.                 }
  274.  
  275.                 ReturnPacket(PrintPacket,PrintPacket -> dp_Res1,PrintPacket -> dp_Res2);
  276.                 break;
  277.             }
  278.  
  279.                 /* We are to leave the town. */
  280.  
  281.             case ACTION_DIE:
  282.             {
  283.                 ReturnPacket(PrintPacket,DOSTRUE,0);
  284.  
  285.                 goto FallOff;
  286.             }
  287.  
  288.                 /* Say what? */
  289.  
  290.             default:
  291.             {
  292.                 ReturnPacket(PrintPacket,DOSFALSE,ERROR_ACTION_NOT_KNOWN);
  293.  
  294.                 break;
  295.             }
  296.         }
  297.     }
  298.  
  299. FallOff:PrintNode -> dn_Task = NULL;
  300.  
  301. /*    SendText("FallOff");*/
  302.  
  303.         /* Tell printer process to shut down. */
  304.  
  305.     if(QueueProc)
  306.     {
  307.         SendCustomMsg(-1);
  308.  
  309. /*        SendText("Handshake...");*/
  310.  
  311.         Wait(SIG_SHAKE);
  312.     }
  313.  
  314. /*    SendText("Close mxm");*/
  315.  
  316.         /* Close the library. */
  317.  
  318.     if(MXMBase)
  319.         CloseLibrary((struct Library *)MXMBase);
  320.  
  321. /*    SendText("Close far");*/
  322.  
  323. /*    if(FarBase)*/
  324. /*        CloseLibrary(FarBase);*/
  325. }
  326.  
  327.     /* SendCustomMsg(Slot):
  328.      *
  329.      *    Send a message to the printer process.
  330.      */
  331.  
  332. VOID *
  333. SendCustomMsg(Slot)
  334. LONG Slot;
  335. {
  336.     struct Message *TempMsg = (struct Message *)AllocRem(sizeof(struct Message),MEMF_PUBLIC | MEMF_CLEAR);
  337.  
  338.     if(TempMsg)
  339.     {
  340.         TempMsg -> mn_Node . ln_Name    = (char *)Slot;
  341.         TempMsg -> mn_ReplyPort        = NULL;
  342.         TempMsg -> mn_Length        = sizeof(struct Message);
  343.  
  344. /*        SendText("SendCustomMsg -> %ld",Slot);*/
  345.  
  346.         PutMsg(&QueueProc -> pr_MsgPort,TempMsg);
  347.     }
  348.  
  349.     return((VOID *)TempMsg);
  350. }
  351.  
  352.     /* QueueEntryPoint():
  353.      *
  354.      *    The printer process. This revision now send the data
  355.      *    to be printed to the process rather than to process
  356.      *    the data itself. This saves some amount of time when
  357.      *    calling processes send their files while the printer
  358.      *    is still busy.
  359.      */
  360.  
  361. VOID
  362. QueueEntryPoint()
  363. {
  364.     struct MsgPort        *PrinterPort;
  365.     struct Message        *QueueMsg;
  366.     LONG             GoOn,Slot,i;
  367.     struct PopSupport     PopSupport;
  368.  
  369.     geta4();
  370.  
  371.         /* We want the error pop-ups to beep. */
  372.  
  373.     PopSupport . ps_Flags    = PS_BEEP;
  374.     PopSupport . ps_TimeOut    = 0;
  375.  
  376.         /* Open everything this process needs. */
  377.  
  378.     if(!(PrinterPort = (struct MsgPort *)CreatePort(NULL,0)))
  379.         goto FallOff;
  380.  
  381.     if(!(PrinterDevice = (struct IOStdReq *)CreateStdIO(PrinterPort)))
  382.         goto FallOff;
  383.  
  384.     if(OpenDevice("printer.device",0,PrinterDevice,0))
  385.         goto FallOff;
  386.  
  387.     Preferences = &((struct PrinterData *)PrinterDevice -> io_Device) -> pd_Preferences;
  388.  
  389.         /* We're running. */
  390.  
  391.     Signal((struct Task *)HandlerProc,SIG_SHAKE);
  392.  
  393. /*    SendText("Process running.");*/
  394.  
  395.         /* Go into infinite loop. */
  396.  
  397.     FOREVER
  398.     {
  399.         WaitPort(&QueueProc -> pr_MsgPort);
  400.  
  401.         while(QueueMsg = GetMsg(&QueueProc -> pr_MsgPort))
  402.         {
  403.             GoOn = TRUE;
  404.  
  405.             if((Slot = (LONG)QueueMsg -> mn_Node . ln_Name) != -1)
  406.             {
  407. /*                SendText("Slot %ld",Slot);*/
  408.  
  409.                 while(DataSegs[Slot])
  410.                 {
  411.                     if(GoOn)
  412.                     {
  413.                         if(!PrintData((UBYTE *)DataSegs[Slot] -> Buffer,DataSegs[Slot] -> Length,&PopSupport))
  414.                             GoOn = FALSE;
  415.                     }
  416.  
  417.                     DataSegs[Slot] = DeleteSeg(DataSegs[Slot]);
  418.                 }
  419.  
  420.                 /* New: produce a working formfeed if last page
  421.                  * wasn't 100% occupied.
  422.                  */
  423.  
  424.                 if(Preferences -> PaperType == SINGLE && LinesDone < Preferences -> PaperLength)
  425.                 {
  426.                     LONG ToDo = Preferences -> PaperLength - LinesDone;
  427.  
  428.                     for(i = 0 ; i < ToDo ; i++)
  429.                         PrintIt((APTR)"\n",1);
  430.                 }
  431.  
  432.                 GoOn = TRUE;
  433.  
  434.                 Available[Slot] = TRUE;
  435.             }
  436.             else
  437.                 GoOn = FALSE;
  438.  
  439.             FreeRem(QueueMsg);
  440.  
  441.             LinesDone = ColumnsDone = 0;
  442.  
  443.             if(!GoOn)
  444.                 goto FallOff;
  445.         }
  446.     }
  447.  
  448. FallOff:if(PrinterDevice)
  449.     {
  450. /*        SendText("CloseDevice");*/
  451.  
  452.         if(PrinterDevice -> io_Device)
  453.             CloseDevice(PrinterDevice);
  454.  
  455. /*        SendText("DeleteStdIO");*/
  456.  
  457.         DeleteStdIO(PrinterDevice);
  458.     }
  459.  
  460. /*    SendText("DeletePort");*/
  461.  
  462.     if(PrinterPort)
  463.         DeletePort(PrinterPort);
  464.  
  465.     Forbid();
  466.  
  467.     Signal((struct Task *)HandlerProc,SIG_SHAKE);
  468.  
  469.     QueueProc = NULL;
  470. }
  471.  
  472.     /* PrintIt(Buffer,Length):
  473.      *
  474.      *    The real printer interface.
  475.      */
  476.  
  477. LONG
  478. PrintIt(Buffer,Length)
  479. APTR Buffer;
  480. LONG Length;
  481. {
  482.     if(Buffer && Length)
  483.     {
  484.         LONG Error;
  485.  
  486.         PrinterDevice -> io_Command    = CMD_WRITE;
  487.         PrinterDevice -> io_Data    = Buffer;
  488.         PrinterDevice -> io_Length    = Length;
  489.  
  490.         Error = DoIO(PrinterDevice); 
  491.  
  492.         return(Error);
  493.     }
  494.  
  495.     return(IOERR_BADLENGTH);
  496. }
  497.  
  498.     /* PrintData(Buffer,Length,PopSupport):
  499.      *
  500.      *    This one send the data to the printer.
  501.      */
  502.  
  503. LONG
  504. PrintData(Buffer,Length,PopSupport)
  505. UBYTE *Buffer;
  506. LONG Length;
  507. struct PopSupport *PopSupport;
  508. {
  509.     LONG i,InBuff = 0,PaperWidth = Preferences -> PrintRightMargin - Preferences -> PrintLeftMargin;
  510.  
  511. /*    SendText("Buffer %lx Length %ld",Buffer,Length);*/
  512.  
  513.     memset(LineStack,0,MAXPRINT);
  514.  
  515.     if(Buffer)
  516.     {
  517.         for(i = 0 ; i < Length ; i++)
  518.         {
  519.             LineStack[InBuff++] = Buffer[i];
  520.             ColumnsDone++;
  521.  
  522.             if(ColumnsDone == PaperWidth || Buffer[i] == '\n')
  523.             {
  524.                 if(ColumnsDone == PaperWidth || ColumnsDone == MAXPRINT)
  525.                 {
  526.                     LineStack[InBuff++] = '\n';
  527.                     ColumnsDone++;
  528.                 }
  529.  
  530.                 LineStack[InBuff] = 0;
  531.  
  532.                 if(PrintIt((APTR)LineStack,InBuff))
  533.                     PopRequest(NULL,"Print-Handler Problem:","Error copying text to printer,\nplease    check   cables   and\nsupplies.",NULL,"Continue?",FALSE,PopSupport);
  534.  
  535.                 if((++LinesDone) == Preferences -> PaperLength)
  536.                 {
  537.                     LinesDone = 0;
  538.  
  539.                     if(Preferences -> PaperType == SINGLE)
  540.                     {
  541.                         if(!PopRequest(NULL,"Print-Handler Request:","Finished   with   current  page,\nplease   insert  next  sheet  of\npaper.","Continue","Abort",TRUE,NULL))
  542.                             return(FALSE);
  543.                     }
  544.                 }
  545.  
  546.                 ColumnsDone = InBuff = 0;
  547.  
  548.                 memset(LineStack,0,MAXPRINT);
  549.             }
  550.         }
  551.  
  552.         if(InBuff)
  553.             PrintIt((APTR)LineStack,InBuff);
  554.     }
  555.  
  556.     return(TRUE);
  557. }
  558.  
  559.     /* CreateSeg(Buffer,Length):
  560.      *
  561.      *    Create a new data segment.
  562.      */
  563.  
  564. struct DataSeg *
  565. CreateSeg(Buffer,Length)
  566. APTR Buffer;
  567. LONG Length;
  568. {
  569.     struct DataSeg *NewSeg;
  570.  
  571. /*    SendText("CreateSeg Length %ld",Length);*/
  572.  
  573.     if(NewSeg = (struct DataSeg *)AllocRem(sizeof(struct DataSeg),MEMF_PUBLIC | MEMF_CLEAR))
  574.     {
  575.         if(NewSeg -> Buffer = (APTR)AllocRem(Length,MEMF_PUBLIC | MEMF_CLEAR))
  576.         {
  577.             CopyMem(Buffer,NewSeg -> Buffer,Length);
  578.             NewSeg -> Length = Length;
  579.  
  580. /*            SendText("Buffer %lx",NewSeg -> Buffer);*/
  581.  
  582.             return(NewSeg);
  583.         }
  584.  
  585.         FreeRem(NewSeg);
  586.     }
  587.  
  588.     return(NULL);
  589. }
  590.  
  591.     /* DeleteSeg(OldSeg):
  592.      *
  593.      *    Delete a data segment.
  594.      */
  595.  
  596. struct DataSeg *
  597. DeleteSeg(OldSeg)
  598. struct DataSeg *OldSeg;
  599. {
  600.     struct DataSeg *NextSeg = NULL;
  601.  
  602.     if(OldSeg)
  603.     {
  604.         NextSeg = OldSeg -> NextSeg;
  605.  
  606.         if(OldSeg -> Buffer && OldSeg -> Length)
  607.         {
  608.             FreeRem(OldSeg -> Buffer);
  609.  
  610.             OldSeg -> Buffer = NULL;
  611.             OldSeg -> Length = 0;
  612.         }
  613.  
  614.         FreeRem(OldSeg);
  615.     }
  616.  
  617.     return(NextSeg);
  618. }
  619.  
  620.     /* ReturnPacket(Packet,res1,res2):
  621.      *
  622.      *    Returns a packet to a handler.
  623.      */
  624.  
  625. VOID
  626. ReturnPacket(Packet,Result1,Result2)
  627. struct DosPacket *Packet;
  628. ULONG Result1,Result2;
  629. {
  630.     struct MsgPort *ReplyPort = Packet -> dp_Port;
  631.  
  632.         /* Fill in the results and fill in the
  633.          * sender MsgPort.
  634.          */
  635.  
  636.     Packet -> dp_Res1 = Result1;
  637.     Packet -> dp_Res2 = Result2; 
  638.     Packet -> dp_Port = &HandlerProc -> pr_MsgPort;
  639.  
  640.         /* Link Message & Packet together. */
  641.  
  642.     Packet -> dp_Link -> mn_Node . ln_Name = (char *)Packet;
  643.     Packet -> dp_Link -> mn_Node . ln_Succ = NULL;
  644.     Packet -> dp_Link -> mn_Node . ln_Pred = NULL;
  645.  
  646.         /* Send the packet... */ 
  647.  
  648.     PutMsg(ReplyPort,Packet -> dp_Link); 
  649. }
  650.  
  651.     /* TaskWait():
  652.      *
  653.      *    Lets the process wait for a DOS-Packet.
  654.      */
  655.  
  656. struct DosPacket *
  657. TaskWait()
  658. {
  659.     struct Message *PrintMessage;
  660.  
  661.         /* Wait for the packet. */
  662.  
  663.     WaitPort(&HandlerProc -> pr_MsgPort);
  664.  
  665.         /* Pick it up. */
  666.  
  667.     PrintMessage = (struct Message *)GetMsg(&HandlerProc -> pr_MsgPort);
  668.  
  669.         /* Return real pointer. */
  670.  
  671.     return((struct DosPacket *)PrintMessage -> mn_Node . ln_Name);
  672.